package maze;

/**
 * Directions, in the usual sense - <strong>Mechanisms</strong>,
 * <strong>Controls</strong>.
 * <p>
 * Abstraction of direction, since the 'bot deals with degree values but
 * Controls only cares about the four cardinal directions.
 * </p>
 * 
 * Development stage: should be usable as-is.
 * 
 * @author Calvin
 */
public enum Direction {
        /**
         * Designated null-value
         */
        NORTH,
        /**
         * 180 deg from NORTH; i.e., orthogonal to NORTH
         */
        SOUTH,
        /**
         * 90 deg from NORTH
         */
        EAST,
        /**
         * 270 deg from NORTH
         */
        WEST;

        /**
         * @return The reverse of this Direction.
         */
        public Direction reverse() {
                switch (this) {
                case NORTH:
                        return SOUTH;
                case SOUTH:
                        return NORTH;
                case EAST:
                        return WEST;
                case WEST:
                        return EAST;
                default:
                        return null;
                }
        }

        /**
         * @return Angle in degrees clockwise from {@value #NORTH}.
         */
        public Double angle() {
                switch (this) {
                case NORTH:
                        return 0.0;
                case EAST:
                        return 90.0;
                case SOUTH:
                        return 180.0;
                case WEST:
                        return 270.0;
                default:
                        return null;
                }
        }

        /**
         * Return the cardinal direction corresponding *roughly* to the specified
         * angle.
         * 
         * @param angle
         *            Angle in degrees to estimate.
         * @return Direction object corresponding to angle.
         */
        public static Direction estimate(double angle) {
                if (angle < -45) {
                        return estimate(angle + 360);
                } else if (angle < 45) {
                        return NORTH;
                } else if (angle < 135) {
                        return EAST;
                } else if (angle < 225) {
                        return SOUTH;
                } else if (angle < 315) {
                        return WEST;
                } else {
                        return estimate(angle - 360);
                }
        }

        /**
         * Describes this Direction
         */
        public String toString() {
                switch (this) {
                case NORTH:
                        return "North";
                case EAST:
                        return "East";
                case SOUTH:
                        return "South";
                case WEST:
                        return "West";
                default:
                        return null;
                }
        }
}
